//
//  YLHUD.swift
//  Swift-Codedase
//
//  Created by xyanl on 2023/9/5.
//

import Foundation
import Lottie

class YLHUD: MBProgressHUD {
    
    private static let afterDelay: TimeInterval = 2.0
    
    typealias Completion = (() -> Void)
    
    // 提示类型
    enum HintType {
        case success // 成功
        case error // 错误
        case warning // 警告
        case hint // 提示
        case verified // 验证通过
        case unverified // 未验证
        case imageName(String) // 自定义图片名
    }
    
    // 获取提示的图片名
    static func getHintImageName(type: HintType) -> String {
        switch type {
        case .success:
            return "YLProgressHUD.bundle/success"
        case .error:
            return "YLProgressHUD.bundle/error"
        case .warning:
            return "YLProgressHUD.bundle/warning"
        case .hint:
            return "YLProgressHUD.bundle/hint"
        case .verified:
            return "YLProgressHUD.bundle/verified"
        case .unverified:
            return "YLProgressHUD.bundle/unverified"
        case .imageName(let name):
            return name
        }
    }
    
    
    
    // MARK: - 文本
    /// 简单文本
    /// - Parameters:
    ///   - message: 文本内容.
    ///   - toView: 在 toView 上显示.
    ///   - delay: 延迟数秒自动消失,0:不自动消失,需要手动操作,默认:2秒.
    ///   - offset: 边框相对于视图中心的偏移量. 默认:CGPointZero 中心.
    ///   - completion: 消失后的回调.
    static func showMessage(
        _ message: String,
        toView: UIView = xKeyWindowView,
        delay: TimeInterval = afterDelay,
        offset: CGPoint = CGPointZero,
        completion: Completion? = nil
    ) {
        
        var hud: MBProgressHUD!
        if let topHud = MBProgressHUD.forView(toView) {
            // 找到尚未完成的最顶层HUD子视图并返回它
            hud = topHud
        } else {
            //初始化HUD窗口,并置于当前的View当中显示
            hud = MBProgressHUD.showAdded(to: toView, animated: true)
        }
        
        hud.mode = .text
        // 当隐藏时从父视图中移除HUD.
        hud.removeFromSuperViewOnHide = true
        
        hud.label.text = message
        hud.label.numberOfLines = 0
        hud.label.font = .monospacedSystemFont(ofSize: 16.0, weight: .bold)
        // 文字的颜色
        hud.contentColor = .white
        hud.areDefaultMotionEffectsEnabled = false
        /**
         通过 animationType 属性可以设置提示框消失动画,有如下三种可选值:
         .fade:逐渐透明消失（默认值）
         .zoomOut:逐渐缩小并透明消失
         .zoomIn:逐渐放大并透明消失
         */
        hud.animationType = .zoomOut
        // 正方形
        hud.isSquare = false
        // 背景框的背景色
        hud.bezelView.color = UIColor(light: .black.setAlpha(0.8), dark: .lightGray)
        // 纯色的
        hud.bezelView.style = .solidColor
        // 背景色
        hud.backgroundColor = .clear
        // 边框相对于视图中心的偏移量.
        hud.offset = offset
        
        if delay == 0 {
            // 不自动隐藏, 手动隐藏
        } else {
            // 延迟数秒,直到HUD被隐藏.
            hud.hide(animated: true, afterDelay: delay)
        }
        
        hud.completionBlock = {
            completion?()
        }
    }
    
    // MARK: - 菊花
    /// 菊花加载
    /// - Parameters:
    ///   - message: 文本消息
    ///   - toView: 在 toView 上显示
    ///   - delay: 延迟数秒自动消失, 0:不自动消失,需要手动操作, 默认:0
    ///   - completion: 消失后的回调
    static func showActivity(
        _ message: String = "",
        toView: UIView = xKeyWindowView,
        delay: TimeInterval = 0,
        completion: Completion? = nil
    ) {
        
        DispatchQueue.main.async {
            
            var hud: MBProgressHUD!
            if let topHud = MBProgressHUD.forView(toView) {
                // 找到尚未完成的最顶层HUD子视图并返回它
                hud = topHud
            } else {
                //初始化HUD窗口,并置于当前的View当中显示
                hud = MBProgressHUD.showAdded(to: toView, animated: true)
            }
            
            hud.mode = .indeterminate
            // 当隐藏时从父视图中移除HUD.
            hud.removeFromSuperViewOnHide = true
            if !message.isEmpty {
                hud.label.text = message
                hud.label.numberOfLines = 0
                hud.label.font = .monospacedSystemFont(ofSize: 16.0, weight: .bold)
            }
            // 内容的颜色(包含label,菊花,进度条)
            hud.contentColor = .white
            hud.areDefaultMotionEffectsEnabled = false
            /**
             通过 animationType 属性可以设置提示框消失动画,有如下三种可选值:
             .fade:逐渐透明消失（默认值）
             .zoomOut:逐渐缩小并透明消失
             .zoomIn:逐渐放大并透明消失
             */
            hud.animationType = .zoomOut
            
            hud.isSquare = true
            
            // 背景框的背景色
            hud.bezelView.color = UIColor.color(r: 0, g: 0, b: 0, alpha: 0.8)
            // 纯色的
            hud.bezelView.style = .solidColor
            // 背景色
            hud.backgroundColor = .clear
            
            if delay == 0 {
                // 不自动隐藏, 手动隐藏
            } else {
                // 延迟数秒,直到HUD被隐藏.
                hud.hide(animated: true, afterDelay: delay)
            }
            
            hud.completionBlock = {
                completion?()
            }
        }
    }
    
    // MARK: - 进度
    /// 进度
    /// - Parameters:
    ///   - message: 文本消息
    ///   - toView: 在 toView 上显示
    ///   - mode: 模式,不包含 .CustomView
    ///   - progress: 进度，从0.0到1.0。默认为0.0。
    /// - Returns: 返回 HUD
    @discardableResult
    static func showProgress(
        _ message: String = "",
        toView: UIView = xKeyWindowView,
        mode: MBProgressHUDMode,
        progress: Float = 0.0
    ) -> MBProgressHUD {
        var hud: MBProgressHUD!
        if let topHud = MBProgressHUD.forView(toView) {
            // 找到尚未完成的最顶层HUD子视图并返回它
            hud = topHud
        } else {
            //初始化HUD窗口,并置于当前的View当中显示
            hud = MBProgressHUD.showAdded(to: toView, animated: true)
        }
        
        hud.mode = mode
        // 进度，从0.0到1.0。默认为0.0。
        hud.progress = progress
        // 当隐藏时从父视图中移除HUD.
        hud.removeFromSuperViewOnHide = true
        if !message.isEmpty {
            hud.label.text = message
            hud.label.numberOfLines = 0
            hud.label.font = .monospacedSystemFont(ofSize: 16.0, weight: .bold)
        }
        // 内容的颜色(包含label,菊花,进度条)
        hud.contentColor = .white
        hud.areDefaultMotionEffectsEnabled = false
        
        hud.animationType = .zoomOut
        
        hud.isSquare = false
        
        // 背景框的背景色
        hud.bezelView.color = UIColor.color(r: 0, g: 0, b: 0, alpha: 0.8)
        // 纯色的
        hud.bezelView.style = .solidColor
        // 背景色
        hud.backgroundColor = .clear
        
        return hud
    }
    
}

// MARK: - 隐藏
extension YLHUD {
    /// 隐藏HUD
    /// - Parameter from: HUD所在的视图
    static func hideHUD(_ from: UIView = xKeyWindowView) {
        DispatchQueue.main.async {
            MBProgressHUD.hide(for: from, animated: true)
        }
    }
}


// MARK: - 自定义 Lottie
extension YLHUD {
    static func showLottie(
        _ message: String = "",
        toView: UIView = xKeyWindowView,
        delay: TimeInterval = 0,
        isShowBackground: Bool = false,
        completion: Completion? = nil
    ) {
        let customView = YLHUDCustomView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
        YLHUD.showCustomView(
            message,
            toView: toView,
            customView: customView,
            delay: delay,
            isShowBackground: isShowBackground,
            completion: completion
        )
    }
}

// MARK: - 自定义 CustomView
extension YLHUD {
    /// 自定义
    /// - Parameters:
    ///   - message: 文本消息
    ///   - toView: 在 toView 上显示
    ///   - customView: 自定义view
    ///   - isShowBackground: 是否显示背景框
    /// - Returns: 返回 HUD
    @discardableResult
    static func showCustomView(
        _ message: String = "",
        toView: UIView = xKeyWindowView,
        customView: UIView,
        delay: TimeInterval = 0,
        isShowBackground: Bool = true,
        completion: Completion? = nil
    ) -> MBProgressHUD  {
        var hud: MBProgressHUD!
        if let topHud = MBProgressHUD.forView(toView) {
            // 找到尚未完成的最顶层HUD子视图并返回它
            hud = topHud
        } else {
            //初始化HUD窗口,并置于当前的View当中显示
            hud = MBProgressHUD.showAdded(to: toView, animated: true)
        }
        
        hud.mode = .customView
        // 当隐藏时从父视图中移除HUD.
        hud.removeFromSuperViewOnHide = true
        if !message.isEmpty {
            hud.label.text = message
            hud.label.numberOfLines = 0
            hud.label.font = .monospacedSystemFont(ofSize: 16.0, weight: .bold)
        }
        // 内容的颜色(包含label,菊花,进度条)
        hud.contentColor = .white
        hud.areDefaultMotionEffectsEnabled = false
        
        hud.animationType = .zoomOut
        
        if isShowBackground {
            // 背景框的背景色
            hud.bezelView.color = UIColor(light: .black.setAlpha(0.8), dark: .lightGray)
            // 背景色
            hud.backgroundColor = .clear
            
        } else {
            // 背景框的背景色
            hud.bezelView.color = .clear
            // 背景色
            hud.backgroundColor = UIColor(light: .black.setAlpha(0.3), dark: .lightGray)
        }
        
        // 纯色的
        hud.bezelView.style = .solidColor
        
        hud.customView = customView
        
        if delay > 0 {
            // 延迟数秒,直到HUD被隐藏.
            hud.hide(animated: true, afterDelay: delay)
        }
        
        hud.completionBlock = {
            completion?()
        }
        
        return hud
    }
    
    
    /// 轻留的加载动画
    /// - Parameter toView: 在 toView 上显示
    static func showQingLiu(_ toView: UIView = xKeyWindowView) {
        
        var marr: [UIImage] = []
        
        for i in 0...74 {
            let image = UIImage(named: "ic_hud_\(i).png")!
            marr.append(image)
        }
        
        let imageView = UIImageView()
        
        imageView.backgroundColor = .clear
        imageView.clipsToBounds = true
        //imageView的动画图片是数组images
        imageView.animationImages = marr
        //按照原始比例缩放图片，保持纵横比
        imageView.contentMode = .scaleAspectFit
        //切换动作的时间3秒，来控制图像显示的速度有多快，
        imageView.animationDuration = 2
        //动画的重复次数，想让它无限循环就赋成0
        imageView.animationRepeatCount = 0
        // 开始播放
        imageView.startAnimating()
        
        let hud = YLHUD.showCustomView(toView: toView, customView: imageView)
        // 正方形
        hud.isSquare = true
        // 背景框的背景色
        hud.bezelView.color = .clear
        // 纯色的
        hud.bezelView.style = .solidColor
        // 背景色
        hud.backgroundColor = .clear
    }
    
    /// 显示自定义提示
    /// - Parameters:
    ///   - type: 提示类型
    ///   - message: 文本
    ///   - toView: 在 toView 上显示
    ///   - isSquare: 正方形
    ///   - delay: 延迟数秒自动消失,0:不自动消失,需要手动操作,默认:2秒.
    ///   - completion: 消失后的回调.
    @discardableResult
    static func showHint(_ type: HintType, _ message: String = "", toView: UIView = xKeyWindowView, isSquare: Bool = false, delay: TimeInterval = afterDelay, completion: Completion? = nil) -> MBProgressHUD {
        
        let imageView = UIImageView(image: UIImage.init(named: getHintImageName(type: type)))
        
        let hud = YLHUD.showCustomView(message, toView: toView, customView: imageView, delay: delay, completion: completion)
        // 正方形
        hud.isSquare = isSquare
        
        return hud
    }
}



class YLHUDCustomView: UIView {
    
    private let animView: LottieAnimationView = {
        let animView: LottieAnimationView = LottieAnimationView(name: "Lottie_loading")
        // 循环播放
        animView.loopMode = .loop
        // 默认值到后台暂停，到前台继续播放完，然后暂停
        // pauseAndRestore 后台到前台，接着没播放完的继续播放，如果是已经暂停了，则从开始开始播放，需要循环播放的动画，使用该属性
        animView.backgroundBehavior = .pauseAndRestore
        return animView
    }()
    
    override var intrinsicContentSize: CGSize {
        return CGSize(width: 100, height: 100)
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupUI()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func willMove(toSuperview newSuperview: UIView?) {
        
        if let _ = newSuperview {
            animView.play()
        } else {
            animView.stop()
        }
    }
    
    func setupUI() {
        animView.frame = self.bounds
        addSubview(animView)
    }
}
